/*
Borealis Library
A library of commonly used hydrological modeling building blocks

Copyright (C) 2008  Chris Marsh

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOGGER_H
#define LOGGER_H

#include <string>
#include <windows.h>

namespace Borealis
{

	//******************************
	// Enum: MessageType
	//		Used to determine what preset message type to use.
	//
	// Values:
	//		MSG_SUCCESS - A success occurred
	//		MSG_INFO - General information.
	//		MSG_WARN - Greater severity than the others, but not yet fatal.
	//		MSG_ERROR - Most likely a fatal error occurred
	//
	// See Also:
	//		<LogMessage>
	//******************************
	enum MESSAGETYPE
	{
		MSG_SUCCESS = 1,	
		MSG_INFO = 2,
		MSG_WARN = 3,
		MSG_ERROR = 4,
	};


	//******************************
	// Class: Logger
	//		Provides logging support for Tempest in a RTF format. As well, logging level can be
	//		set, which allows for logging of only specific events. This is currently a singleton class
	//		that allows for global logging to one file. This will be changed at a latter date so that multiple files
	//		can be used. Currently may not be thread safe.
	//
	// Platform:
	//		Currently Windows ONLY.
	//
	// Credit:
	//		This class is an implementation with a few modifications of Eamonn Doherty's LogFile found at http://www.gamedev.net/reference/programming/features/rtflog/. A lot
	//		of the comments are his, just modified to work with ND. As well, the syntax description below is all his.
	//
	// Syntax:
	// The log file outputs logging information to an RTF file. C-style file I/O is used because it is
	// slightly faster than iostream. Text passed to the writer may use the following formatting tags:
	// 
	// [<colour>]              -   Text after this tag will be coloured specified colour.
	// <colour> can be: BLACK, WHITE, GREY, RED, GREEN, BLUE, CYAN, YELLOW,
	// MAGENTA, DARK_RED, DARK_GREEN, DARK_BLUE, LIGHT_RED, LIGHT_GREEN,
	// LIGHT_BLUE, ORANGE.
	// 
	// [PLAIN]                 -   Text after this tag will be unformatted
	// 
	// [B], [/B]               -   Text in between these two tags will be bolded
	// 
	// [I], [/I]               -   Text in between these two tags will be italicized
	// 
	// [U], [/U]               -   Text in between these two tags will be underlined
	// 
	// [S], [/S]               -   Text in between these two tags will have a line through it
	// 
	// [SUB], [/SUB]           -   Text in between these two tags will be a subscript
	// 
	// [SUPER], [/SUPER]       -   Text in between these two tags will be a superscript
	// 
	// [LEFT]                  -   Text will be left-justified (this is the default justification)
	// 
	// [RIGHT]                 -   Text will be right-justified
	// 
	// [CENTER]                -   Text will be center-justified
	// 
	// [FULL]                  -   Text will be full-justified
	// 
	// [TITLE], [/TITLE]       -   Text in between these two tags will be size 20
	// 
	// [H], [/H]               -   Text in between these two tags will be size 12
	//******************************
	class Logger
	{
	public:
		
		static Logger& GetInstance();

		//************************************
		// Function:  Init
		//		Opens the  log file in preparation for logging.
		//		Init will create a new log file for each call to this.
		//		If a log is already open, it will silently exit, keeping the old log file
		//
		// Todo: 
		//		Add append
		//
		// Parameters:
		//		const string& sFile - Log file name
		//
		// Throws:
		//		Never
		//
		// Returns:
		//		void
		//************************************
		void InitLog(const std::string& sFile);
		
		//************************************
		// Function:  Close
		//		Closes the log file
		//
		// Parameters:
		//		None
		//
		// Throws:
		//		std::runtime_error
		//
		// Returns:
		//		void
		//************************************
		void Close ();

		
		//************************************
		// Function:  IsOpen
		//		Determines if a log file is currently open
		//
		// Parameters:
		//		None
		//
		// Throws:
		//		Never
		//
		// Returns:
		//		bool - True on Open
		//************************************
		bool IsOpen();

		
		//************************************
		// Function:  LogString
		//		Write a formated string to the log file. If no file has been opened a default file "Borealis_Debug_log.log" is used.
		//
		// Parameters:
		//		string sText - String to write
		//
		// Throws:
		//		Never
		//
		// Returns:
		//		void 
		//************************************
		void LogString (std::string sText);

		
		//************************************
		// Function:  LogMessage
		//		Writes a specially formated message to the log file. If no file has been opened a default file "Borealis_Debug_log.log" is used.
		//		See Also <MESSAGETYPE>
		//
		// Parameters:
		//		const string &sSource - Left hand side of the message. To write <Foo:Bar> Message in bar, <Foo:Bar> is this param.
		//		const string& sMessage - Right hand side of the message
		//		MESSAGETYPE messageType - Message type.
		//
		// Throws:
		//		Never
		//
		// Returns:
		//		void 
		//************************************
		void LogMessage (const std::string &sSource, const std::string& sMessage, MESSAGETYPE messageType);


	private:
		//RTF file's colour table
		enum COLOURTABLE
		{
			BLACK = 0,
			WHITE = 1,
			GREY = 2,
			RED = 3,
			GREEN = 4,
			BLUE = 5,
			CYAN = 6,
			YELLOW = 7,
			MAGENTA = 8,
			DARK_RED = 9,
			DARK_GREEN = 10,
			DARK_BLUE = 11,
			LIGHT_RED = 12,
			LIGHT_GREEN = 13,
			LIGHT_BLUE = 14,
			ORANGE = 15,
		};

		//Add RTF formatting to a string using formatting tags
		void DoFormatting (std::string* sText);

		//Replace all instances of a tag in a string with equivalent RTF formatting
		void ReplaceTag (std::string* sText, const std::string& sTag, const std::string& sReplacement);

		//Writes a string directly to the logfile
		void WriteString (const std::string& sText);

		Logger();
		~Logger();

		//File loaded flag
		bool m_loaded;

		//Handle to the file
		HANDLE m_file;

		//Filename
		std::string m_filename;

		static Logger m_instance;

	};
}
#endif